package org.wattdepot.cli.command;

import java.util.ArrayList;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.cli.processor.CommandLineInterface;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.resource.source.jaxb.Source;
import org.wattdepot.util.tstamp.Tstamp;

/**
 * Class for Total Power for FuelTypes.
 * 
 * @author Remy Baumgarten
 * @author Kevin Chiogioji
 * 
 */
public class TotalPowerFuelType extends CommandLineInterface implements WattDepotCliCommand {

  protected static final String waste = "waste";
  protected static final String coal = "coal";
  protected static final String LSFO = "LSFO";

  /**
   * Converts URL to Source.
   * 
   * @param url - Full URL
   * @return - source without the add-ons
   */
  public String urlToSource(String url) {
    return url.substring(url.lastIndexOf('/') + 1, url.length());
  }

  /**
   * Gets the fueltypes of the sources.
   * 
   * @param source - Specified source
   * @param type - Specified fuel type
   * @return sourceList - List of subsources that match the specified fuel type
   * @throws BadXmlException -
   * @throws ResourceNotFoundException -
   * @throws NotAuthorizedException -
   * @throws MiscClientException -
   */
  public List<String> getFuelType(Source source, String type) throws MiscClientException,
      NotAuthorizedException, ResourceNotFoundException, BadXmlException {
    List<String> sourceList = new ArrayList<String>();
    if (source.isSetSubSources()) {
      List<String> urlList = source.getSubSources().getHref();
      String sub, fuelType;
      for (int i = 0; i < urlList.size(); i++) {
        sub = urlToSource(urlList.get(i));
        if (client.getSource(sub).isVirtual()) {
          Source current = client.getSource(sub);
          urlList.addAll(current.getSubSources().getHref());
          continue;
        }
        fuelType = client.getSource(sub).getProperty("fuelType");
        if (type.equals(fuelType)) {
          sourceList.add(sub);
        }
      }
    }
    return sourceList;
  }

  /**
   * Command 2.12 - Displays the total power generated for a specified fuel type.
   * 
   * @param args - List of parameters read in from the command line.
   * @return - string of total power generated for the specified source, fuel type
   */
  @Override
  public String doCommand(List<String> args) {
    String source = args.get(0);
    Source currentSource = null;
    String fuelType = args.get(2);
    Double totalPowerGenerated = 0.0;
    List<String> fuelMap;
    StringBuffer buff = new StringBuffer(255);

    try {

      // Check if valid fuel type was entered
      if (!("waste".equals(fuelType) || "coal".equals(fuelType) || "LSFO".equals(fuelType))) {
        buff.append("Invalid fuel type.");
        return buff.toString();
      }

      XMLGregorianCalendar timestamp = Tstamp.makeTimestamp(args.get(1));

      currentSource = client.getSource(source);

      // Get list of sources that match the specified fuel type
      fuelMap = getFuelType(currentSource, fuelType);

      // Calculate the total power generated
      for (int i = 0; i < fuelMap.size(); i++) {
        totalPowerGenerated =
            totalPowerGenerated + client.getPowerGenerated(fuelMap.get(i), timestamp);
      }

      // Convert to MW
      totalPowerGenerated = totalPowerGenerated / 1000000;

      buff.append(totalPowerGenerated);
      buff.append(" MW");

      return buff.toString();
    }

    catch (MiscClientException mce) {
      return errorClient;
    }
    catch (BadXmlException bxe) {
      return errorXML;
    }
    catch (ResourceNotFoundException rnfe) {
      return error404;
    }
    catch (NotAuthorizedException nae) {
      return error401;
    }
    catch (Exception e) {
      return errorTimeStamp;
    }
  }
}
